package com.sc.util.data;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;

public class HttpClient {
	private static Log log = LogFactory.getLog(HttpClient.class);

	private static final String DEFAULT_ENCODE = "utf-8";

	/**
	 * GET请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @return 内容字符串
	 */
	public static String getUrlAsString(String url) {
		return getUrlAsString(url, null, DEFAULT_ENCODE);
	}

	/**
	 * GET请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @param params 请求参数
	 * @return 内容字符串
	 */
	public static String getUrlAsString(String url, Map<String, String> params) {
		return getUrlAsString(url, params, DEFAULT_ENCODE);
	}

	/**
	 * GET请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @param params 请求参数
	 * @param encode 编码方式
	 * @return 内容字符串
	 */
	public static String getUrlAsString(String url, Map<String, String> params, String encode) {
		// 开始时间
		long t1 = System.currentTimeMillis();
		// 获得httpGet对象
		HttpGet httpGet = getHttpGet(url, params, encode);
		// 发送请求
		String result = executeHttpRequest(httpGet, null, encode);
		// 结束时间
		long t2 = System.currentTimeMillis();
		// 调试信息
		log.debug("url:" + url);
		if(params!=null){
			log.debug("params:" + params.toString());
		}
		log.debug("encode:" + encode);
		log.debug("result:" + result);
		log.debug("consume time:" + ((t2 - t1)));
		// 返回结果
		return result;
	}

	public static byte[] postUrlAsOutStream(String url, byte[] xmlBytes, String encode) {
		HttpPost httpPost = new HttpPost(url);
		DefaultHttpClient client = null;
		try {
			// 创建HttpClient对象
			client = new DefaultHttpClient();
			ByteArrayInputStream bis = new ByteArrayInputStream(xmlBytes);
			InputStreamEntity reqEntity = new InputStreamEntity(bis, -1);
			reqEntity.setContentEncoding(encode);
			reqEntity.setContentType("binary/octet-stream");
			reqEntity.setChunked(true);
			httpPost.setEntity(reqEntity);

			client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
			client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, SOCKET_TIMEOUT);
			HttpResponse response = client.execute(httpPost);
			// 如果成功
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				InputStream is = response.getEntity().getContent();
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				int i = -1;
				while ((i = is.read()) != -1) {
					baos.write(i);
				}
				return baos.toByteArray();
			}
			// 如果失败
			else {
				StringBuffer errorMsg = getErrorMsg(response);
				log.error("HttpResonse Error:" + errorMsg);
			}
		} catch (Exception e) {
			log.error("http连接异常", e);
			throw new RuntimeException("http连接异常");
		} finally {
			try {
				client.getConnectionManager().shutdown();
			} catch (Exception e) {
				log.error("finally HttpClient shutdown error", e);
			}
		}
		return null;
	}

	public static String postUrlAsOutStream(String url, String params, Map<String, String> reqHeader) {
		HttpPost httpPost = new HttpPost(url);
		DefaultHttpClient client = null;
		String result = null;
		try {
			// 创建httpClient对象
			client = new DefaultHttpClient();
			ByteArrayInputStream bis = new ByteArrayInputStream(params.getBytes());
			InputStreamEntity reqEntity = new InputStreamEntity(bis, -1);
			reqEntity.setContentEncoding(DEFAULT_ENCODE);
			reqEntity.setContentType("binary/octet-stream");
			reqEntity.setChunked(true);
			httpPost.setEntity(reqEntity);

			// 设置连接超时时间
			client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
			// 设置Socket超时时间
			client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, SOCKET_TIMEOUT);
			// 设置请求头信息
			if (reqHeader != null) {
				for (String name : reqHeader.keySet()) {
					httpPost.addHeader(name, reqHeader.get(name));
				}
			}
			// 获得返回结果
			HttpResponse response = client.execute(httpPost);
			// 如果成功
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				result = EntityUtils.toString(response.getEntity());
			}
			// 如果失败
			else {
				StringBuffer errorMsg = getErrorMsg(response);
				log.error("HttpResonse Error:" + errorMsg);
			}
		} catch (Exception e) {
			log.error("http连接异常", e);
			throw new RuntimeException("http连接异常");
		} finally {
			try {
				client.getConnectionManager().shutdown();
			} catch (Exception e) {
				log.error("finally HttpClient shutdown error", e);
			}
		}
		return result;

	}

	/**
	 * POST请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @return 内容字符串
	 */
	public static String postUrlAsString(String url) {
		return postUrlAsString(url, null, null, null);
	}

	/**
	 * POST请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @param params 内容参数
	 * @return 内容字符串
	 */
	public static String postUrlAsString(String url, Map<String, String> params) {
		return postUrlAsString(url, params, null, "utf-8");
	}

	/**
	 * POST请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @param params 请求参数
	 * @return
	 * 
	 */
	public static String postUrlAsString(String url, Map<String, String> params, String encoding) {
		return postUrlAsString(url, params, null, encoding);
	}

	public static String postUrlAsString(String url, Map<String, String> params, Map<String, String> reqHeader) {
		return postUrlAsString(url, params, reqHeader, null);
	}

	/**
	 * POST请求，结果以字符串形式返回
	 * 
	 * @param url 请求地址
	 * @param params 请求参数
	 * @param reqHeader 请求投内容
	 * @return
	 * 
	 */
	public static String postUrlAsString(String url, Map<String, String> params, Map<String, String> reqHeader, String encode) {
		// 开始时间
		long t1 = System.currentTimeMillis();
		// 获得httpPost对象
		HttpPost httpPost = getHttpPost(url, params, encode);
		// 发送请求
		String result = executeHttpRequest(httpPost, reqHeader, encode);
		// 结束时间
		long t2 = System.currentTimeMillis();
		// 调试信息
		log.info("url:" + url + " , params:" + params.toString());
		log.info("consume time:" + ((t2 - t1)));
		// 返回结果
		return result;
	}

	/**
	 * 请求体为json
	 */
	public static String postUrlJson(String url, String jsonparams, String encode) {
		// 开始时间
		long t1 = System.currentTimeMillis();
		// 获得httpPost请求实例
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader("Content-Type", "application/json");
		try {
			httpPost.setEntity(new StringEntity(jsonparams));
		} catch (UnsupportedEncodingException e) {
			log.warn("UnsupportedEncodingException " + e.getMessage() + "  jsonparams:" + jsonparams);
			throw new RuntimeException(e);
		}
		// 响应结果
		String result = executeHttpRequest(httpPost, null, encode);
		// 结束时间
		long t2 = System.currentTimeMillis();
		// 返回结果
		log.info("url:" + url + " , params:" + jsonparams);
		log.info("consume time:" + ((t2 - t1)));
		return result;
	}

	/**
	 * 请求体为xml
	 * 
	 * @param url
	 * @param jsonparams
	 * @param encode
	 * @return
	 */
	public static String postUrlXml(String url, String xml, String encode) {
		// 开始时间
		long t1 = System.currentTimeMillis();
		// 获得httpPost请求实例
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader("Content-Type", "application/xml");
		try {
			httpPost.setEntity(new StringEntity(xml));
		} catch (UnsupportedEncodingException e) {
			log.warn("UnsupportedEncodingException " + e.getMessage() + "  jsonparams:" + xml);
			throw new RuntimeException(e);
		}
		// 响应结果
		String result = executeHttpRequest(httpPost, null, encode);
		// 结束时间
		long t2 = System.currentTimeMillis();
		// 返回结果
		log.info("url:" + url + " , params:" + xml);
		log.info("consume time:" + ((t2 - t1)));
		return result;
	}

	private static HttpGet getHttpGet(String url, Map<String, String> params, String encode) {
		StringBuffer buf = new StringBuffer(url);
		if (params != null) {
			// 地址增加?或者&
			String flag = (url.indexOf('?') == -1) ? "?" : "&";
			// 添加参数
			for (String name : params.keySet()) {
				buf.append(flag);
				buf.append(name);
				buf.append("=");
				try {
					buf.append(URLEncoder.encode(params.get(name), encode));
				} catch (UnsupportedEncodingException e) {
					log.error("URLEncoder Error,encode=" + encode + ",param=" + params.get(name), e);
				}
				flag = "&";
			}
		}
		HttpGet httpGet = new HttpGet(buf.toString());
		return httpGet;
	}

	private static HttpPost getHttpPost(String url, Map<String, String> params, String encode) {
		HttpPost httpPost = new HttpPost(url);
		if (params != null) {
			List<NameValuePair> form = new ArrayList<NameValuePair>();
			for (String name : params.keySet()) {
				form.add(new BasicNameValuePair(name, params.get(name)));
			}
			try {
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, encode);
				httpPost.setEntity(entity);
			} catch (UnsupportedEncodingException e) {
				log.error("UrlEncodedFormEntity Error,encode=" + encode + ",form=" + form, e);
			}
		}
		return httpPost;
	}

	static int SOCKET_TIMEOUT = 60000;
	static int CONNECTION_TIMEOUT = 30000;

	private static String executeHttpRequest(HttpUriRequest request, Map<String, String> reqHeader, String encode) {
		DefaultHttpClient client = null;
		String result = null;
		try {
			// 创建httpClient对象
			client = new DefaultHttpClient();
			// 设置超时时间
			client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
			// 设置Socket超时时间
			client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, SOCKET_TIMEOUT);
			// 设置请求投信息
			if (reqHeader != null) {
				for (String name : reqHeader.keySet()) {
					request.addHeader(name, reqHeader.get(name));
				}
			}
			// 获得返回结果
			org.apache.http.HttpResponse response = client.execute(request);
			// 如果成功
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				result = EntityUtils.toString(response.getEntity(), encode);
			}
			// 如果失败
			else {
				StringBuffer errorMsg = getErrorMsg(response);
				log.error("HttpResonse Error:" + errorMsg);
			}
		} catch (Exception e) {
			log.error("http连接异常", e);
			throw new RuntimeException("http连接异常");
		} finally {
			try {
				client.getConnectionManager().shutdown();
			} catch (Exception e) {
				log.error("finally HttpClient shutdown error", e);
			}
		}
		return result;
	}

	/**
	 * 下载文件保存到本地
	 * 
	 * @param path 文件保存位置
	 * @param url 文件地址
	 * @throws IOException
	 */
	public static boolean downloadFile(String path, String url, Map<String, String> params) {
		log.debug("path:" + path);
		log.debug("url:" + url);
		DefaultHttpClient client = null;
		try {

			client = new DefaultHttpClient();
			// HttpGet httpGet = getHttpGet(url, null, null);
			HttpPost httpPost = getHttpPost(url, params, DEFAULT_ENCODE);
			HttpResponse response = client.execute(httpPost);
			// 如果成功
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				byte[] result = EntityUtils.toByteArray(response.getEntity());
				BufferedOutputStream bw = null;
				try {
					// 创建文件对象
					File f = new File(path);
					// 创建文件路径
					if (!f.getParentFile().exists())
						f.getParentFile().mkdirs();
					// 写入文件
					bw = new BufferedOutputStream(new FileOutputStream(path));
					bw.write(result);
					return true;
				} catch (Exception e) {
					log.error("保存文件错误,path=" + path + ",url=" + url, e);
				} finally {
					try {
						if (bw != null)
							bw.close();
					} catch (Exception e) {
						log.error("finally BufferedOutputStream shutdown close", e);
					}
				}
			} else {// 如果失败
				StringBuffer errorMsg = getErrorMsg(response);
				log.error("HttpResonse Error:" + errorMsg);
			}
		} catch (ClientProtocolException e) {
			log.error("下载文件保存到本地,htto连接异常,path=" + path + ",url=" + url, e);
		} catch (IOException e) {
			log.error("下载文件保存到本地,htto连接异常,path=" + path + ",url=" + url, e);
		} finally {
			try {
				client.getConnectionManager().shutdown();
			} catch (Exception e) {
				log.error("finally HttpClient shutdown error", e);
			}
		}
		return false;
	}

	private static StringBuffer getErrorMsg(HttpResponse response) {
		StringBuffer errorMsg = new StringBuffer();
		errorMsg.append("httpStatus:");
		errorMsg.append(response.getStatusLine().getStatusCode());
		errorMsg.append(response.getStatusLine().getReasonPhrase());
		errorMsg.append(", Header: ");
		Header[] headers = response.getAllHeaders();
		for (Header header : headers) {
			errorMsg.append(header.getName());
			errorMsg.append(":");
			errorMsg.append(header.getValue());
		}
		return errorMsg;
	}

	public static void main(String[] args) throws IOException {
		// String result = getUrlAsString("http://www.gewara.com/");
		// System.out.println(result);
		// downloadFile("e:/000.gif",
		// "http://www.anxin1688.com/images/lottery/banner_602X157.gif");
	}
}
